package rsee.com;

import java.util.Vector;

import rsee.com.EyeSourceTrans.TransState;



import android.util.Log;

import com.video.h264.EyeProtocolParser;
import com.video.h264.EyeProtocolParser.StreamDataFormat;



public class EyeSourceMgr implements EyeSourceTrans.EyeSourceTransCallBack {
	// inherit by VideoView/AudioView
	private int Version;
	private boolean addStream;
	public interface EyeSourceCallBack {
		void onUpdateData(EyeFrameData data);
		void onUpdateState(TransState state, int errCode);
		void onGetStreamInfo(EyeProtocolParser.StreamDataFormat streamInfo);
	}
	
	//================ Instance ================
	private static EyeSourceMgr mInstance = null;
	public static EyeSourceMgr getInstance() {
		if (null != mInstance)
			return mInstance;
		
		try {
			mInstance = new EyeSourceMgr();
		} catch (Exception e) {
			// TODO: handle exception
		}
		
		return mInstance;
	}
	
	private Vector<TransWrap> mTransSet = null;
	private EyeSourceMgr() {
		mTransSet = new Vector();
	}
	
	private TransWrap searchWrap(SourceIdent ident) {
		int count = mTransSet.size();
		TransWrap mWrap =null;
		for (int i=0; i<count ;i++) {
			TransWrap wrap = mTransSet.get(i);
			SourceIdent wrapIdent = wrap.getIdent();
			if (wrapIdent.isSameIdent(ident))
			{	//TODO
//				if(Version==1&&ident.getChanIndex()!=wrapIdent.getChanIndex()
//						&&wrapIdent.getChannelGroupIdex()!=null
//						&&ident.getChannelGroupIdex()!=wrapIdent.getChannelGroupIdex())
//				{
//					byte []channelGroup = new byte[wrapIdent.getChannelGroupIdex().length+1];
//					for(int j=0;j<channelGroup.length;j++)
//					{
//						if(j==channelGroup.length-1)
//							channelGroup[j] = 	(byte)(ident.getChanIndex()+1);
//						else
//						channelGroup[j] = wrapIdent.getChannelGroupIdex()[j];
//					}
//					wrapIdent.setChannelGroupIndex(channelGroup);
//					ident.setChannelGroupIndex(channelGroup);
//				}
//				return wrap;
				if(null==mWrap)
				mWrap = wrap;
			}
		}
		return mWrap;
		//return null;
	}
	
	public int getVersion()
	{
		return Version;
	}
	
	private void addWrap(TransWrap wrap) {
		TransWrap exist = searchWrap(wrap.getIdent());
		if (null != exist)
			return;
		
		mTransSet.add(wrap);
	}
	
	private void removeWrap(TransWrap wrap) {
		mTransSet.remove(wrap);
	}
	//================ TransMap ================
	private class TransWrap {
		private Vector<EyeSourceCallBack> mListeners = null;
		private EyeSourceTrans mTrans = null;
		
		public TransWrap(EyeSourceTrans trans) {
			mTrans = trans;
			mListeners = new Vector<EyeSourceMgr.EyeSourceCallBack>();
		}
		
		public EyeSourceTrans getSourceTrans() {
			return mTrans;
		}
		
		public SourceIdent getIdent() {
			if (null == mTrans)
				return null;
			SourceIdent ident = mTrans.getIdent();
			return ident;
		}
		
		// Listener Control
		public void addListener(EyeSourceCallBack listener) {
			boolean exist = searchListener(listener);
			if (exist) {
				// already exist
				return;
			}
			mListeners.add(listener);
		}
		
		public void removeListener(EyeSourceCallBack listener) {
			boolean exist = searchListener(listener);
			if (!exist)
				return;
			
			mListeners.remove(listener);
		}
		
		public int listenerCount() {
			int count = mListeners.size();
			return count;
		}
		
		public boolean searchListener(EyeSourceCallBack listener) {
			int count = listenerCount();//mListeners.size();
			for (int i=0; i<count; i++) {
				EyeSourceCallBack item = mListeners.get(i);
				if (item == listener)
					return true;
			}
			
			return false;
		}
		
		//Listener Method
		public void onUpdateData(EyeFrameData data) {
			//Log.e("EyeSourceMgr", "data Channel Id:"+data.getChannelId());
			int count = listenerCount();//mListeners.size();
			for (int i=0; i<count; i++) {
				EyeSourceCallBack listener = mListeners.get(i);
				listener.onUpdateData(data);
			}
		}
		
		public void onUpdateState(TransState state, int errCode) {
			 int count = listenerCount();//mListeners.size();
			Log.e("sourceMgr:", "count:"+count);
			for (int i=0; i<count; i++) {

				Log.e("sourceMgr:", "updataState"+i);
				EyeSourceCallBack listener = mListeners.get(i);
				listener.onUpdateState(state, errCode);
			}
		}
		
		public void onGetStreamInfo(EyeProtocolParser.StreamDataFormat streamInfo) {
            int count = mListeners.size();
            for (int i = 0; i < count; i++) {
                EyeSourceCallBack listener = mListeners.get(i);
                listener.onGetStreamInfo(streamInfo);
            }
		}
	}
	
	public boolean requestSource(SourceIdent ident, EyeSourceCallBack listener,int  streamMode, int dataType,int Version,byte[] channelGroup) {
		if (null == ident || null == listener)
			return false;
		this.Version = Version;
		addStream = false;
		TransWrap wrap = searchWrap(ident);
		if (null != wrap) {
			wrap.addListener(listener);
			if(addStream)
			{
				requestAddChannelStream(ident, listener,ident.getChannelGroupIdex(), (byte)dataType);
			}
			
			return true;
		}
		
		EyeSourceTrans trans = EyeSourceTrans.createSourceTrans(ident, this, streamMode, dataType,Version,channelGroup);
		if (null == trans)
			return false;
		
		try {
			wrap = new TransWrap(trans);
		} catch (Exception e) {
			// TODO: handle exception
			return false;
		}
		
		wrap.addListener(listener);
		addWrap(wrap);
		trans.request();
		
		return true;
	}	
	
	public void removeSource(SourceIdent ident, EyeSourceCallBack listener) {
		if (null == ident || null == listener)
			return;
		
		TransWrap wrap = searchWrap(ident);
		if (null == wrap) {
			return;
		}
		
		wrap.removeListener(listener);
		int count = wrap.listenerCount();
		if (0 != count)
			return;
		
		EyeSourceTrans trans = wrap.getSourceTrans();
		trans.close();
		
		// remove from set
		removeWrap(wrap);
	}
	
	public EyeSourceTrans searchSource(SourceIdent ident, EyeSourceCallBack listener) {
		TransWrap wrap = searchWrap(ident);
		if (null == wrap)
			return null;
		
		boolean existListener = wrap.searchListener(listener);
		if (!existListener)
			return null;
		
		EyeSourceTrans trans = wrap.getSourceTrans();
		return trans;
	}
	
    public boolean searchSource(SourceIdent ident) {
        TransWrap wrap = searchWrap(ident);
        if (null == wrap)
            return false;

        return true;
    }
	
	public boolean canChanSwitch(SourceIdent ident, EyeSourceCallBack listener) {
		TransWrap wrap = searchWrap(ident);
		if (null == wrap)
			return false;
		
		boolean existListener = wrap.searchListener(listener);
		if (!existListener)
			return false;
		
		int count = wrap.listenerCount();
		if (count > 1)
			return false;
		
		return true;
	}
	
	public void requestChanSwitch(SourceIdent ident, EyeSourceCallBack listener, byte dstChanIndex) {
		TransWrap wrap = searchWrap(ident);
		if (null == wrap)
			return;
		
		boolean existListener = wrap.searchListener(listener);
		if (!existListener)
			return;
		
		EyeSourceTrans trans = wrap.getSourceTrans();
		boolean isNet = trans.isNet();
		if (!isNet)
			return;
		
		((EyeSourceTransNet)trans).chanSwitch(dstChanIndex);
	}
	
	public void requestChanGroupSwitch(SourceIdent ident, EyeSourceCallBack listener, byte []srcChanIndex,byte []dstChanIndex) {
		TransWrap wrap = searchWrap(ident);
		if (null == wrap)
			return;
		
		boolean existListener = wrap.searchListener(listener);
		if (!existListener)
			return;
		
		EyeSourceTrans trans = wrap.getSourceTrans();
		boolean isNet = trans.isNet();
		if (!isNet)
			return;
		
		((EyeSourceTransNet)trans).chanGroupSwitch(srcChanIndex,dstChanIndex);
	}
	
	public void requestAddChannelStream(SourceIdent ident, EyeSourceCallBack listener,byte []addChannel,byte dataType) {
		TransWrap wrap = searchWrap(ident);
		if (null == wrap)
			return;
		
		boolean existListener = wrap.searchListener(listener);
		if (!existListener)
			return;
		
		EyeSourceTrans trans = wrap.getSourceTrans();
		boolean isNet = trans.isNet();
		if (!isNet)
			return;
		
		((EyeSourceTransNet)trans).addChannelStream(addChannel, dataType);
	}
	
	public void requestStopChannelStream(SourceIdent ident, EyeSourceCallBack listener,byte videoChannel,byte audioChannel) {
		TransWrap wrap = searchWrap(ident);
		if (null == wrap)
			return;
		
		boolean existListener = wrap.searchListener(listener);
		if (!existListener)
			return;
		
		EyeSourceTrans trans = wrap.getSourceTrans();
		boolean isNet = trans.isNet();
		if (!isNet)
			return;
		
		((EyeSourceTransNet)trans).stopChannelStream(videoChannel, audioChannel);
	}
	
	public void remoteControl(SourceIdent ident, EyeSourceCallBack listener, EyeRemoteCommand cmd) {
		TransWrap wrap = searchWrap(ident);
		if (null == wrap)
			return;
		
		boolean existListener = wrap.searchListener(listener);
		if (!existListener)
			return;
		
		EyeSourceTrans trans = wrap.getSourceTrans();
		boolean isNet = trans.isNet();
		if (!isNet)
			return;
		
		((EyeSourceTransNet)trans).remoteControl(cmd);
	}
	
	public boolean getAudio(SourceIdent ident, EyeSourceCallBack listener) {
		TransWrap wrap = searchWrap(ident);
		if (null == wrap)
			return false;		
		EyeSourceTrans trans = wrap.getSourceTrans();		
		return ((EyeSourceTransNet)trans).getAudio();
	}
	
	
	public void setAudio(SourceIdent ident, EyeSourceCallBack listener,boolean audio) {
		TransWrap wrap = searchWrap(ident);
		if (null == wrap)
			return;		
		EyeSourceTrans trans = wrap.getSourceTrans();		
		((EyeSourceTransNet)trans).setAudio(audio);
	}
	
	public boolean getTalk(SourceIdent ident, EyeSourceCallBack listener) {
		TransWrap wrap = searchWrap(ident);
		if (null == wrap)
			return false;		
		EyeSourceTrans trans = wrap.getSourceTrans();		
		return ((EyeSourceTransNet)trans).getTalk();
	}
	
	public int getVideoFPS(SourceIdent ident, EyeSourceCallBack listener) {
		TransWrap wrap = searchWrap(ident);
		if (null == wrap)
			return 0;		
		EyeSourceTrans trans = wrap.getSourceTrans();		
		return ((EyeSourceTransNet)trans).getVideoFPS();
	}
	
	public void setTalk(SourceIdent ident, EyeSourceCallBack listener,boolean talk) {
		TransWrap wrap = searchWrap(ident);
		if (null == wrap)
			return;		
		EyeSourceTrans trans = wrap.getSourceTrans();		
		((EyeSourceTransNet)trans).setTalk(talk);
	}
	
	//================ EyeSourceTrans.EyeSourceTransCallBack ================
	public void onUpdateData(SourceIdent ident, EyeFrameData data) {
		TransWrap wrap = searchWrap(ident);
		if (null == wrap)
			return;
		
		wrap.onUpdateData(data);
	}

	public void onUpdateState(SourceIdent ident, TransState state, int errCode) {
		TransWrap wrap = searchWrap(ident);
		if (null == wrap)
			return;
		
		wrap.onUpdateState(state, errCode);
	}

    public void onGetStreamInfo(SourceIdent ident,
            StreamDataFormat stream_format) {
        TransWrap wrap = searchWrap(ident);
        if (null == wrap)
            return;
        
        wrap.onGetStreamInfo(stream_format);
    }	
}
